bitkeeper revision 1.1010.1.10 (40dfd40bszbCgYF9OJJKWOo1n7X8hw)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Mon, 28 Jun 2004 08:17:15 +0000 (08:17 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Mon, 28 Jun 2004 08:17:15 +0000 (08:17 +0000)
Rename xenctl, move things around.

21 files changed:
.rootkeys
tools/Makefile
tools/examples/xc_physinfo.py [deleted file]
tools/examples/xm_dom_control.py [deleted file]
tools/examples/xmdefaults
tools/examples/xmnetbsd [new file with mode: 0644]
tools/xen/lib/ext/__init__.py [new file with mode: 0644]
tools/xen/lib/util/__init__.py [new file with mode: 0644]
tools/xen/lib/util/console_client.py [new file with mode: 0644]
tools/xen/lib/util/ip.py [new file with mode: 0644]
tools/xen/lib/util/tempfile.py [new file with mode: 0644]
tools/xen/lib/xm/main.py
tools/xen/setup.py
tools/xenctl/Makefile [deleted file]
tools/xenctl/lib/__init__.py [deleted file]
tools/xenctl/lib/console_client.py [deleted file]
tools/xenctl/lib/ip.py [deleted file]
tools/xenctl/lib/tempfile.py [deleted file]
tools/xenctl/lib/utils.py [deleted file]
tools/xenctl/setup.py [deleted file]
tools/xu/Makefile [new file with mode: 0644]

index 1aabafc723b37900bf9e1065c2068097f8b01470..8418e7c6689930f7f6524d6f4daaca9715039f09 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40278d91ZjLhxdjjrGe8HEdwHLj5xQ tools/examples/netbsd
 401d7e16NpnVrFSsR7lKKKfTwCYvWA tools/examples/xc_dom_control.py
 401d7e16RJj-lbtsVEjua6HYAIiKiA tools/examples/xc_dom_create.py
-403b7cf7J7FsSSoEPGhx6gXR4pIdZg tools/examples/xc_physinfo.py
-40c9c4684Wfg8VgMKtRFa_ULi2e_tQ tools/examples/xm_dom_control.py
 40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py
 40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
+40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
 40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
 3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
 40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
 40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
+40dfd40aMOhnw_cQLve9462UR5yYxQ tools/xen/lib/ext/__init__.py
+40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/xen/lib/util/__init__.py
+4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xen/lib/util/console_client.py
+40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xen/lib/util/ip.py
+4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xen/lib/util/tempfile.py
 40c9c468SNuObE_YWARyS0hzTPSzKg tools/xen/lib/xend/Args.py
 40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
 40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
 40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
 40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
 40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
-4055ee41IfFazrwadCH2J72nz-A9YA tools/xenctl/Makefile
-4055ee4b_4Rvns_KzE12csI14EKK6Q tools/xenctl/lib/__init__.py
-4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xenctl/lib/console_client.py
-40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xenctl/lib/ip.py
-4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xenctl/lib/tempfile.py
-3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xenctl/lib/utils.py
-4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
 40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend-old/Makefile
 4055ad95Se-FqttgxollqOAAHB94zA tools/xend-old/lib/__init__.py
 4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend-old/lib/blkif.py
 403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
 403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
 4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
+40dfd40a0QtsSGigB9TCpVGWZmhlNA tools/xu/Makefile
 40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/xu/lib/__init__.py
 40dc4076pVeE1kEEWzcUaNZin65kCA tools/xu/lib/domain_controller.h
 40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/xu/lib/xu.c
index 69b05709f6a725afc25a4a49798c599bc22bf894..908f49b682fb624131e9b56fd8abc4410a8850d0 100644 (file)
@@ -5,17 +5,14 @@ all:
        $(MAKE) -C misc
        $(MAKE) -C examples
        $(MAKE) -C xentrace
-       $(MAKE) -C xenctl
        $(MAKE) -C xen
 
 install: all
        $(MAKE) -C xc install
        $(MAKE) -C xu install
        $(MAKE) -C misc install
-       $(MAKE) -C xenctl install
        $(MAKE) -C examples install
        $(MAKE) -C xentrace install
-       $(MAKE) -C xenctl install
        $(MAKE) -C xen install
 
 dist: $(TARGET)
@@ -28,6 +25,5 @@ clean:
        $(MAKE) -C misc clean
        $(MAKE) -C examples clean
        $(MAKE) -C xentrace clean
-       $(MAKE) -C xenctl clean
        $(MAKE) -C xen clean
 
diff --git a/tools/examples/xc_physinfo.py b/tools/examples/xc_physinfo.py
deleted file mode 100644 (file)
index 0d9db79..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-
-# Get information about the physical host machine
-
-import Xc
-
-xc = Xc.new()
-
-info = xc.physinfo()
-
-fmt_info = [ ( 'CPU cores', info['cores']),
-             ('Hyperthreads per core', info['ht_per_core']),
-             ('CPU Speed (MHz)', info['cpu_khz'] / 1000),
-             ('Total physical mem (MB)', info['total_pages'] / 256),
-             ('Free physical mem (MB)', info['free_pages'] / 256) ]
-      
-
-for (item, val) in fmt_info:
-    print "%-23s" % item, ':', val
-
diff --git a/tools/examples/xm_dom_control.py b/tools/examples/xm_dom_control.py
deleted file mode 100755 (executable)
index 0cb9b10..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import re
-import string
-import time
-import os
-import os.path
-import signal
-
-from xenmgr import sxp
-from xenmgr.XendClient import server
-
-# usage: xc_dom_control [command] <params>
-#
-# this script isn't very smart, but it'll do for now.
-#
-
-def usage (rc=0):
-    if rc:
-        out = sys.stderr
-    else:
-        out = sys.stdout
-    print >> out, """
-Usage: %s [command] <params>
-
-  help                   -- print usage
-  pause     [dom]        -- pause a domain
-  unpause   [dom]        -- un-pause a domain
-  shutdown  [dom] [[-w]] -- request a domain to shutdown (can specify 'all')
-                            (optionally wait for complete shutdown)
-  destroy   [dom]        -- immediately terminate a domain
-  pincpu    [dom] [cpu]  -- pin a domain to the specified CPU
-  suspend   [dom] [file] -- write domain's memory to a file and terminate
-                           (resume by re-running xc_dom_create with -L option)
-  unwatch   [dom]        -- kill the auto-restart daemon for a domain
-  list                   -- print info about all domains
-  listvbds               -- print info about all virtual block devs
-  cpu_bvtset [dom] [mcuadv] [warp] [warpl] [warpu]
-                         -- set BVT scheduling parameters for domain
-  cpu_bvtslice [slice]   -- set default BVT scheduler slice
-  cpu_atropos_set [dom] [period] [slice] [latency] [xtratime]
-                         -- set Atropos scheduling parameters for domain
-  cpu_rrobin_slice [slice] -- set Round Robin scheduler slice
-  vif_stats [dom] [vif]  -- get stats for a given network vif
-  vif_addip [dom] [vif] [ip]  -- add an IP address to a given vif
-  vif_setsched [dom] [vif] [bytes] [usecs] -- rate limit vif bandwidth
-  vif_getsched [dom] [vif] -- print vif's scheduling parameters
-  vbd_add [dom] [uname] [dev] [mode] -- make disk/partition uname available to 
-                            domain as dev e.g. 'vbd_add 2 phy:sda3 hda1 w'
-  vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev' 
-""" % sys.argv[0]
-    if rc: sys.exit(rc)
-
-if len(sys.argv) < 2: usage(1)
-cmd = sys.argv[1]
-
-#todo: replace all uses of xc with the new api.
-import Xc; xc = Xc.new()
-
-rc = ''
-dom = None
-
-
-def auto_restart_pid_file(dom):
-    # The auto-restart daemon's pid file.
-    return '/var/run/xendomains/%d.pid' % dom
-
-def auto_restart_pid(dom):
-    watcher = auto_restart_pid_file(dom)
-    if os.path.isfile(watcher):
-        fd = open(watcher,'r')
-        pid = int(fd.readline())
-    else:
-        pid = None
-    return pid
-def auto_restart_kill(dom):
-    #todo: replace this - tell xend not to restart any more.
-    # Kill a domain's auto restart daemon.
-    pid = auto_restart_pid(dom)
-    if pid:
-        os.kill(pid, signal.SIGTERM)
-
-
-if len( sys.argv ) > 2 and re.match('\d+$', sys.argv[2]):
-    dom = long(sys.argv[2])
-
-if cmd == "help":
-    usage()
-    
-elif cmd == 'pause':
-    rc = server.xend_domain_pause(dom)
-
-elif cmd == 'unpause':
-    rc = server.xend_domain_unpause(dom)    
-
-elif cmd == 'shutdown':
-    doms = []
-    shutdown = []
-    if dom != None:
-        doms = [ dom ]
-    elif sys.argv[2] == 'all':
-        doms = server.xend_domains()
-        doms.remove('0')
-    for d in doms:
-        ret = server.xend_domain_shutdown(d)
-        if ret == 0:
-            shutdown.append(d)
-        else:
-            rc = ret
-
-    wait = (len(sys.argv) == 4 and sys.argv[3] == "-w")
-    if wait:
-        # wait for all domains we shut down to terminate
-        for dom in shutdown:
-            while True:
-                info = server.xend_domain(dom)
-                if not info: break
-                time.sleep(1)
-
-elif cmd == 'destroy':
-    rc = server.xend_domain_halt(dom)    
-
-elif cmd == 'pincpu':
-    if len(sys.argv) < 4: usage(1)
-    cpu = int(sys.argv[3])
-    rc = server.xend_domain_pincpu(dom, cpu)
-
-elif cmd == 'list':
-    print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
-    doms = server.xend_domains()
-    doms.sort()
-    for dom in doms:
-        info = server.xend_domain(dom)
-        d = {}
-        d['dom'] = int(dom)
-        d['name'] = sxp.child_value(info, 'name', '??')
-        d['mem'] = int(sxp.child_value(info, 'memory', '0'))
-        d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
-        d['state'] = sxp.child_value(info, 'state', '??')
-        d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
-        print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)8.2f" % d)
-
-elif cmd == 'unwatch':
-    auto_restart_kill(dom)
-
-elif cmd == 'listvbds':
-    print 'Dom   Dev   Mode   Size(MB)'
-    for dom in server.xend_domains():
-        for vbd in server.xend_domain_vbds(dom):
-            info = server.xend_domain_vbd(vbd)
-            v['vbd'] = vbd
-            v['size'] = int(sxp.get_child_value(info, 'size', '0'))
-            v['mode'] = sxp.get_child_value(info, 'mode', '??')
-            vbd['size_mb'] = vbd['nr_sectors'] / 2048
-            print ('%(dom)-4d  %(vbd)04x  %(mode)-2s      %(size)d' % v)
-
-elif cmd == 'suspend':
-    if len(sys.argv) < 4: usage(1)
-    file = os.path.abspath(sys.argv[3])
-    auto_restart_kill(dom)
-    rc = server.xend_domain_save(dom, file, progress=1)
-
-elif cmd == 'cpu_bvtslice':
-    if len(sys.argv) < 3: usage(1)
-    slice = sys.argv[2]
-    rc = server.xend_node_cpu_bvt_slice_set(slice)
-
-elif cmd == 'cpu_bvtset':
-    if len(sys.argv) < 7: usage(1)
-    (mcuadv, warp, warpl, warpu) = map(int, sys.argv[3:7])
-    
-    rc = server.xend_domain_cpu_bvt_set(dom, mcuadv, warp, warpl, warpu)
-    
-elif cmd == 'vif_stats':
-    if len(sys.argv) < 4: usage(1)
-    vif = int(sys.argv[3])
-
-    print server.xend_domain_vif_stats(dom, vif)
-
-elif cmd == 'vif_addip':
-    if len(sys.argv) < 5: usage(1)
-    vif = int(sys.argv[3])
-    ip  = sys.argv[4]
-    rc = server.xend_domain_vif_addip(dom, vif, ip)
-
-elif cmd == 'vif_setsched':
-    if len(sys.argv) < 6: usage(1)
-    (vif, bytes, usecs) = map(int, sys.argv[3:6])
-    rc = server.xend_domain_vif_scheduler_set(dom, vif, bytes, usecs)
-
-elif cmd == 'vif_getsched':
-    if len(sys.argv) < 4: usage(1)
-    vif = int(sys.argv[3])
-    print server.xend_domain_vif_scheduler_get(dom, vif)
-
-elif cmd == 'vbd_add':
-    if len(sys.argv) < 6: usage(1)
-    uname = sys.argv[3]
-    dev = sys.argv[4]
-    mode = sys.argv[5]
-    try:
-        vbd = server.xend_domain_vbd_add(dom, uname, dev, mode)
-    except StandardError, ex:
-        print "Error:", ex
-        sys.exit(1)
-    print "Added disk/partition %s to domain %d as device %s (%x)" % (uname, dom, dev, vbd)
-
-elif cmd == 'vbd_remove':
-    if len(sys.argv) < 4: usage(1)
-    dev = sys.argv[3]
-    vbd = server.xend_domain_vbd_remove(dom, dev)
-    if vbd < 0:
-       print "Failed"
-       sys.exit(1)
-    else:
-       print "Removed disk/partition attached as device %s (%x) in domain %d" % (dev, vbd, dom)
-
-elif cmd == 'cpu_atropos_set': # args: dom period slice latency xtratime
-    if len(sys.argv) < 6: usage(1)
-    (period, slice, latency, xtratime) = map(int, sys.argv[3:7])
-    rc = server.xend_domain_cpu_atropos_set(
-        dom, period, slice, latency, xtratime)
-
-elif cmd == 'cpu_rrobin_slice':
-    if len(sys.argv) < 3: usage(1)
-    slice = int(sys.argv[2])
-    rc = server.xend_node_rrobin_set(slice=slice)
-
-else:
-    usage(1)
-
-if rc != '':
-    print "return code %d" % rc
index 61ebc5349bc6b6906c0e4450fc9e02b76c48a8f4..311f38e2d058edb4897771ea27b4b8a25b009805 100644 (file)
@@ -44,10 +44,9 @@ cpu = vmid  # set based on vmid (mod number of CPUs)
 # Number of network interfaces. Default is 1.
 #nics=1
 
-# List of MAC addresses for the network interfaces.
-# If there aren't enough addresses for all the interfaces
-# the rest get random MACs.
-#mac = [ "aa:00:00:00:00:11" ]
+# Optionally define mac and/or bridge for the network interfaces.
+# Random MACs are assigned if not given.
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
 
 #----------------------------------------------------------------------------
 # Define the disk devices you want the domain to have access to, and
diff --git a/tools/examples/xmnetbsd b/tools/examples/xmnetbsd
new file mode 100644 (file)
index 0000000..0563239
--- /dev/null
@@ -0,0 +1,102 @@
+#  -*- mode: python; -*-
+#============================================================================
+# Python defaults setup for 'xm create'.
+# Edit this file to reflect the configuration of your system.
+# This file expects the variable 'vmid' to be set.
+#============================================================================
+
+def config_usage ():
+    print >>sys.stderr,"""
+The config file '%s' requires the following variable to be defined:
+ vmid             -- Numeric identifier for the new domain, used to calculate
+                     the VM's IP address and root partition. E.g. -Dvmid=1
+""" % config_file
+
+
+try:
+    vmid = int(vmid) # convert to integer
+except:
+    raise ValueError, "Variable 'vmid' must be an integer"
+
+if vmid <= 0:
+    raise ValueError, "Variable 'vmid' must be greater than 0" 
+
+#----------------------------------------------------------------------------
+# Kernel image file.
+image = "/boot/netbsd"
+
+# The domain build function.
+builder='netbsd'
+
+# Initial memory allocation (in megabytes) for the new domain.
+memory = 16
+
+# A handy name for your new domain.
+name = "NetBSD VM %d" % vmid
+
+#----------------------------------------------------------------------------
+# Define network interfaces.
+
+# Number of network interfaces. Default is 1.
+#nics=1
+
+# Optionally define mac and/or bridge for the network interfaces.
+# Random MACs are assigned if not given.
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
+
+# Specify IP address(es), for the new domain.  You need to
+# configure IP addrs within the domain just as you do normally.  This
+# is just to let Xen know about them so it can route packets
+# appropriately.
+
+#ipaddr = [ xenctl.utils.add_offset_to_ip(xenctl.utils.get_current_ipaddr(),vmid),
+#           xenctl.utils.add_offset_to_ip('169.254.1.0',vmid),
+#           ]
+
+#----------------------------------------------------------------------------
+# Define the disk devices you want the domain to have access to, and
+# what you want them accessible as.
+# Each disk entry is of the form phy:DEV,VDEV,MODE
+# where DEV is the device, VDEV is the device name the domain will see,
+# and MODE is r for read-only, w for read-write.
+
+#disk = [ 'phy:sda%d,sda1,w' % (7+vmid),
+#         'phy:sda6,sda6,r' ]
+
+#----------------------------------------------------------------------------
+# Set the kernel command line for the new domain.
+# You only need to define the IP parameters and hostname if the domain's
+# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
+# You can use 'extra' to set the runlevel and custom environment
+# variables used by custom rc scripts (e.g. VMID=, usr= ).
+
+# Set if you want dhcp to allocate the IP address.
+#dhcp="dhcp"
+# Set netmask.
+#netmask=
+# Set default gateway.
+#gateway=
+# Set the hostname.
+#hostname= "vm%d" % vmid
+
+# Set root device.
+root = "/dev/sda1 ro"
+
+# Root device for nfs.
+#root = "/dev/nfs"
+# The nfs server.
+#nfs_server = '169.254.1.0'  
+# Root directory on the nfs server.
+#nfs_root   = '/full/path/to/root/directory'
+
+# Sets runlevel 4 and the device for /usr.
+#extra = "4 VMID=%d usr=/dev/sda6" % vmid
+extra = "4 VMID=%d bootdev=xennet0" % vmid
+
+
+#----------------------------------------------------------------------------
+# Set according to whether you want the domain  restarted when it exits.
+# The default is False.
+#restart = True
+
+#============================================================================
diff --git a/tools/xen/lib/ext/__init__.py b/tools/xen/lib/ext/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/xen/lib/util/__init__.py b/tools/xen/lib/util/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/tools/xen/lib/util/console_client.py b/tools/xen/lib/util/console_client.py
new file mode 100644 (file)
index 0000000..7ac63ae
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+##############################################
+# Console client for Xen guest OSes
+# Copyright (c) 2004, K A Fraser
+##############################################
+
+import errno, os, signal, socket, struct, sys
+
+from termios import *
+# Indexes into termios.tcgetattr() list.
+IFLAG  = 0
+OFLAG  = 1
+CFLAG  = 2
+LFLAG  = 3
+ISPEED = 4
+OSPEED = 5
+CC     = 6
+
+def __child_death(signum, frame):
+    global stop
+    stop = True
+
+def __recv_from_sock(sock):
+    global stop
+    stop = False
+    while not stop:
+        try:
+            data = sock.recv(1024)
+            os.write(1, data)
+        except socket.error, error:
+            if error[0] != errno.EINTR:
+                raise
+    os.wait()
+
+def __send_to_sock(sock):
+    while 1:
+        data = os.read(0,1024)
+        if ord(data[0]) == ord(']')-64:
+            break
+        try:
+            sock.send(data)
+        except socket.error, error:
+            if error[0] == errno.EPIPE:
+                sys.exit(0)
+            if error[0] != errno.EINTR:
+                raise
+    sys.exit(0)
+
+def connect(host,port):
+    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+    sock.connect((host,port))
+
+    oattrs = tcgetattr(0)
+    nattrs = tcgetattr(0)
+    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
+    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
+    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
+    nattrs[CFLAG] = nattrs[CFLAG] | CS8
+    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
+    nattrs[CC][VMIN] = 1
+    nattrs[CC][VTIME] = 0
+
+    if os.fork():
+        signal.signal(signal.SIGCHLD, __child_death)
+        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
+        tcsetattr(0, TCSAFLUSH, nattrs)
+        try:
+            __recv_from_sock(sock)
+        finally:
+            tcsetattr(0, TCSAFLUSH, oattrs)
+            print
+            print "************ REMOTE CONSOLE EXITED *****************"
+    else:
+        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
+        __send_to_sock(sock)
+
+if __name__ == '__main__':
+    if len(sys.argv) != 3:
+        print sys.argv[0] + " <host> <port>"
+        sys.exit(1)
+    connect(str(sys.argv[1]),int(sys.argv[2]))
diff --git a/tools/xen/lib/util/ip.py b/tools/xen/lib/util/ip.py
new file mode 100644 (file)
index 0000000..8396e0d
--- /dev/null
@@ -0,0 +1,113 @@
+import os
+import re
+import socket
+import struct
+
+def readlines(fd):
+    """Version of readlines safe against EINTR.
+    """
+    import errno
+    
+    lines = []
+    while 1:
+        try:
+            line = fd.readline()
+        except IOError, ex:
+            if ex.errno == errno.EINTR:
+                continue
+            else:
+                raise
+        if line == '': break
+        lines.append(line)
+    return lines
+
+def readline(fd):
+    """Version of readline safe against EINTR.
+    """
+    while 1:
+        try:
+            return fd.readline()
+        except IOError, ex:
+            if ex.errno == errno.EINTR:
+                continue
+            else:
+                raise
+
+##### Networking-related functions
+
+"""Bridge for network backend.
+When bridging is used, eth0 may not have an IP address,
+as it may have been moved onto the bridge.
+"""
+NBE_BRIDGE = 'nbe-br'
+
+def get_current_ipaddr(dev='eth0'):
+    """Return a string containing the primary IP address for the given
+    network interface (default 'eth0').
+    """
+    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
+                       line )
+        if m:
+            return m.group(1)
+    if dev == 'eth0':
+        return get_current_ipaddr(NBE_BRIDGE)
+    return None
+
+def get_current_ipmask(dev='eth0'):
+    """Return a string containing the primary IP netmask for the given
+    network interface (default 'eth0').
+    """
+    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
+                       line )
+        if m:
+            return m.group(1)
+    if dev == 'eth0':
+        return get_current_ipmask(NBE_BRIDGE)
+    return None
+
+def get_current_ipgw(dev='eth0'):
+    """Return a string containing the IP gateway for the given
+    network interface (default 'eth0').
+    """
+    fd = os.popen( '/sbin/route -n' )
+    lines = readlines(fd)
+    for line in lines:
+        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
+                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
+        if m:
+            return m.group(1)
+    if dev == 'eth0':
+        return get_current_ipgw(NBE_BRIDGE)
+    return None
+
+def inet_aton(addr):
+    """Convert an IP addr in IPv4 dot notation into an int.
+    """
+    b = socket.inet_aton(addr)
+    return struct.unpack('!I', b)[0]
+
+def inet_ntoa(n):
+    """Convert an int into an IP addr in IPv4 dot notation.
+    """
+    b = struct.pack('!I', n)
+    return socket.inet_ntoa(b)
+
+def add_offset_to_ip(addr, offset):
+    """Add a numerical offset to an IP addr in IPv4 dot notation.
+    """
+    n = inet_aton(addr)
+    n += offset
+    return inet_ntoa(n)
+
+def check_subnet( ip, network, netmask ):
+    n_ip = inet_aton(ip)
+    n_net = inet_aton(network)
+    n_mask = inet_aton(netmask)
+    return (n_ip & n_mask) == (n_net & n_mask)
+
diff --git a/tools/xen/lib/util/tempfile.py b/tools/xen/lib/util/tempfile.py
new file mode 100644 (file)
index 0000000..756d8c8
--- /dev/null
@@ -0,0 +1,451 @@
+"""Temporary files.
+
+This module provides generic, low- and high-level interfaces for
+creating temporary files and directories.  The interfaces listed
+as "safe" just below can be used without fear of race conditions.
+Those listed as "unsafe" cannot, and are provided for backward
+compatibility only.
+
+This module also provides some data items to the user:
+
+  TMP_MAX  - maximum number of names that will be tried before
+             giving up.
+  template - the default prefix for all temporary names.
+             You may change this to control the default prefix.
+  tempdir  - If this is set to a string before the first use of
+             any routine from this module, it will be considered as
+             another candidate location to store temporary files.
+"""
+
+__all__ = [
+    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
+    "mkstemp", "mkdtemp",                  # low level safe interfaces
+    "mktemp",                              # deprecated unsafe interface
+    "TMP_MAX", "gettempprefix",            # constants
+    "tempdir", "gettempdir"
+   ]
+
+
+# Imports.
+
+import os as _os
+import errno as _errno
+from random import Random as _Random
+
+if _os.name == 'mac':
+    import Carbon.Folder as _Folder
+    import Carbon.Folders as _Folders
+
+try:
+    import fcntl as _fcntl
+    # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
+    # imported, and we don't get an ImportError then.  Provoke
+    # an AttributeError instead in that case.
+    _fcntl.fcntl
+except (ImportError, AttributeError):
+    def _set_cloexec(fd):
+        pass
+else:
+    def _set_cloexec(fd):
+        flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
+        if flags >= 0:
+            # flags read successfully, modify
+            flags |= _fcntl.FD_CLOEXEC
+            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
+
+
+try:
+    import thread as _thread
+except ImportError:
+    import dummy_thread as _thread
+_allocate_lock = _thread.allocate_lock
+
+_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
+if hasattr(_os, 'O_NOINHERIT'):
+    _text_openflags |= _os.O_NOINHERIT
+if hasattr(_os, 'O_NOFOLLOW'):
+    _text_openflags |= _os.O_NOFOLLOW
+
+_bin_openflags = _text_openflags
+if hasattr(_os, 'O_BINARY'):
+    _bin_openflags |= _os.O_BINARY
+
+if hasattr(_os, 'TMP_MAX'):
+    TMP_MAX = _os.TMP_MAX
+else:
+    TMP_MAX = 10000
+
+template = "tmp"
+
+tempdir = None
+
+# Internal routines.
+
+_once_lock = _allocate_lock()
+
+class _RandomNameSequence:
+    """An instance of _RandomNameSequence generates an endless
+    sequence of unpredictable strings which can safely be incorporated
+    into file names.  Each string is six characters long.  Multiple
+    threads can safely use the same instance at the same time.
+
+    _RandomNameSequence is an iterator."""
+
+    characters = ("abcdefghijklmnopqrstuvwxyz" +
+                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+                  "0123456789-_")
+
+    def __init__(self):
+        self.mutex = _allocate_lock()
+        self.rng = _Random()
+        self.normcase = _os.path.normcase
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        m = self.mutex
+        c = self.characters
+        choose = self.rng.choice
+
+        m.acquire()
+        try:
+            letters = [choose(c) for dummy in "123456"]
+        finally:
+            m.release()
+
+        return self.normcase(''.join(letters))
+
+def _candidate_tempdir_list():
+    """Generate a list of candidate temporary directories which
+    _get_default_tempdir will try."""
+
+    dirlist = []
+
+    # First, try the environment.
+    for envname in 'TMPDIR', 'TEMP', 'TMP':
+        dirname = _os.getenv(envname)
+        if dirname: dirlist.append(dirname)
+
+    # Failing that, try OS-specific locations.
+    if _os.name == 'mac':
+        try:
+            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
+                                              _Folders.kTemporaryFolderType, 1)
+            dirname = fsr.as_pathname()
+            dirlist.append(dirname)
+        except _Folder.error:
+            pass
+    elif _os.name == 'riscos':
+        dirname = _os.getenv('Wimp$ScrapDir')
+        if dirname: dirlist.append(dirname)
+    elif _os.name == 'nt':
+        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
+    else:
+        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
+
+    # As a last resort, the current directory.
+    try:
+        dirlist.append(_os.getcwd())
+    except (AttributeError, _os.error):
+        dirlist.append(_os.curdir)
+
+    return dirlist
+
+def _get_default_tempdir():
+    """Calculate the default directory to use for temporary files.
+    This routine should be called exactly once.
+
+    We determine whether or not a candidate temp dir is usable by
+    trying to create and write to a file in that directory.  If this
+    is successful, the test file is deleted.  To prevent denial of
+    service, the name of the test file must be randomized."""
+
+    namer = _RandomNameSequence()
+    dirlist = _candidate_tempdir_list()
+    flags = _text_openflags
+
+    for dir in dirlist:
+        if dir != _os.curdir:
+            dir = _os.path.normcase(_os.path.abspath(dir))
+        # Try only a few names per directory.
+        for seq in xrange(100):
+            name = namer.next()
+            filename = _os.path.join(dir, name)
+            try:
+                fd = _os.open(filename, flags, 0600)
+                fp = _os.fdopen(fd, 'w')
+                fp.write('blat')
+                fp.close()
+                _os.unlink(filename)
+                del fp, fd
+                return dir
+            except (OSError, IOError), e:
+                if e[0] != _errno.EEXIST:
+                    break # no point trying more names in this directory
+                pass
+    raise IOError, (_errno.ENOENT,
+                    ("No usable temporary directory found in %s" % dirlist))
+
+_name_sequence = None
+
+def _get_candidate_names():
+    """Common setup sequence for all user-callable interfaces."""
+
+    global _name_sequence
+    if _name_sequence is None:
+        _once_lock.acquire()
+        try:
+            if _name_sequence is None:
+                _name_sequence = _RandomNameSequence()
+        finally:
+            _once_lock.release()
+    return _name_sequence
+
+
+def _mkstemp_inner(dir, pre, suf, flags):
+    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
+
+    names = _get_candidate_names()
+
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, pre + name + suf)
+        try:
+            fd = _os.open(file, flags, 0600)
+            _set_cloexec(fd)
+            return (fd, file)
+        except OSError, e:
+            if e.errno == _errno.EEXIST:
+                continue # try again
+            raise
+
+    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
+
+
+# User visible interfaces.
+
+def gettempprefix():
+    """Accessor for tempdir.template."""
+    return template
+
+tempdir = None
+
+def gettempdir():
+    """Accessor for tempdir.tempdir."""
+    global tempdir
+    if tempdir is None:
+        _once_lock.acquire()
+        try:
+            if tempdir is None:
+                tempdir = _get_default_tempdir()
+        finally:
+            _once_lock.release()
+    return tempdir
+
+def mkstemp(suffix="", prefix=template, dir=None, text=False):
+    """mkstemp([suffix, [prefix, [dir, [text]]]])
+    User-callable function to create and return a unique temporary
+    file.  The return value is a pair (fd, name) where fd is the
+    file descriptor returned by os.open, and name is the filename.
+
+    If 'suffix' is specified, the file name will end with that suffix,
+    otherwise there will be no suffix.
+
+    If 'prefix' is specified, the file name will begin with that prefix,
+    otherwise a default prefix is used.
+
+    If 'dir' is specified, the file will be created in that directory,
+    otherwise a default directory is used.
+
+    If 'text' is specified and true, the file is opened in text
+    mode.  Else (the default) the file is opened in binary mode.  On
+    some operating systems, this makes no difference.
+
+    The file is readable and writable only by the creating user ID.
+    If the operating system uses permission bits to indicate whether a
+    file is executable, the file is executable by no one. The file
+    descriptor is not inherited by children of this process.
+
+    Caller is responsible for deleting the file when done with it.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    if text:
+        flags = _text_openflags
+    else:
+        flags = _bin_openflags
+
+    return _mkstemp_inner(dir, prefix, suffix, flags)
+
+
+def mkdtemp(suffix="", prefix=template, dir=None):
+    """mkdtemp([suffix, [prefix, [dir]]])
+    User-callable function to create and return a unique temporary
+    directory.  The return value is the pathname of the directory.
+
+    Arguments are as for mkstemp, except that the 'text' argument is
+    not accepted.
+
+    The directory is readable, writable, and searchable only by the
+    creating user.
+
+    Caller is responsible for deleting the directory when done with it.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    names = _get_candidate_names()
+
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, prefix + name + suffix)
+        try:
+            _os.mkdir(file, 0700)
+            return file
+        except OSError, e:
+            if e.errno == _errno.EEXIST:
+                continue # try again
+            raise
+
+    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
+
+def mktemp(suffix="", prefix=template, dir=None):
+    """mktemp([suffix, [prefix, [dir]]])
+    User-callable function to return a unique temporary file name.  The
+    file is not created.
+
+    Arguments are as for mkstemp, except that the 'text' argument is
+    not accepted.
+
+    This function is unsafe and should not be used.  The file name
+    refers to a file that did not exist at some point, but by the time
+    you get around to creating it, someone else may have beaten you to
+    the punch.
+    """
+
+##    from warnings import warn as _warn
+##    _warn("mktemp is a potential security risk to your program",
+##          RuntimeWarning, stacklevel=2)
+
+    if dir is None:
+        dir = gettempdir()
+
+    names = _get_candidate_names()
+    for seq in xrange(TMP_MAX):
+        name = names.next()
+        file = _os.path.join(dir, prefix + name + suffix)
+        if not _os.path.exists(file):
+            return file
+
+    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
+
+class _TemporaryFileWrapper:
+    """Temporary file wrapper
+
+    This class provides a wrapper around files opened for
+    temporary use.  In particular, it seeks to automatically
+    remove the file when it is no longer needed.
+    """
+
+    def __init__(self, file, name):
+        self.file = file
+        self.name = name
+        self.close_called = False
+
+    def __getattr__(self, name):
+        file = self.__dict__['file']
+        a = getattr(file, name)
+        if type(a) != type(0):
+            setattr(self, name, a)
+        return a
+
+    # NT provides delete-on-close as a primitive, so we don't need
+    # the wrapper to do anything special.  We still use it so that
+    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
+    if _os.name != 'nt':
+
+        # Cache the unlinker so we don't get spurious errors at
+        # shutdown when the module-level "os" is None'd out.  Note
+        # that this must be referenced as self.unlink, because the
+        # name TemporaryFileWrapper may also get None'd out before
+        # __del__ is called.
+        unlink = _os.unlink
+
+        def close(self):
+            if not self.close_called:
+                self.close_called = True
+                self.file.close()
+                self.unlink(self.name)
+
+        def __del__(self):
+            self.close()
+
+def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
+                       prefix=template, dir=None):
+    """Create and return a temporary file.
+    Arguments:
+    'prefix', 'suffix', 'dir' -- as for mkstemp.
+    'mode' -- the mode argument to os.fdopen (default "w+b").
+    'bufsize' -- the buffer size argument to os.fdopen (default -1).
+    The file is created as mkstemp() would do it.
+
+    Returns a file object; the name of the file is accessible as
+    file.name.  The file will be automatically deleted when it is
+    closed.
+    """
+
+    if dir is None:
+        dir = gettempdir()
+
+    if 'b' in mode:
+        flags = _bin_openflags
+    else:
+        flags = _text_openflags
+
+    # Setting O_TEMPORARY in the flags causes the OS to delete
+    # the file when it is closed.  This is only supported by Windows.
+    if _os.name == 'nt':
+        flags |= _os.O_TEMPORARY
+
+    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+    file = _os.fdopen(fd, mode, bufsize)
+    return _TemporaryFileWrapper(file, name)
+
+if _os.name != 'posix' or _os.sys.platform == 'cygwin':
+    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
+    # while it is open.
+    TemporaryFile = NamedTemporaryFile
+
+else:
+    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
+                      prefix=template, dir=None):
+        """Create and return a temporary file.
+        Arguments:
+        'prefix', 'suffix', 'directory' -- as for mkstemp.
+        'mode' -- the mode argument to os.fdopen (default "w+b").
+        'bufsize' -- the buffer size argument to os.fdopen (default -1).
+        The file is created as mkstemp() would do it.
+
+        Returns a file object.  The file has no name, and will cease to
+        exist when it is closed.
+        """
+
+        if dir is None:
+            dir = gettempdir()
+
+        if 'b' in mode:
+            flags = _bin_openflags
+        else:
+            flags = _text_openflags
+
+        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+        try:
+            _os.unlink(name)
+            return _os.fdopen(fd, mode, bufsize)
+        except:
+            _os.close(fd)
+            raise
index d03ceae7f2d2504d6ae3081e614d402a386a0615..84abc7a867554e0c0eec888829952509ffe9c882 100644 (file)
@@ -439,7 +439,7 @@ class ProgConsole(Prog):
         if not console:
             self.err("No console information")
         port = sxp.child_value(console, "port")
-        from xenctl import console_client
+        from xen.util import console_client
         console_client.connect("localhost", int(port))
 
 xm.prog(ProgConsole)
index e099e0016606a710de88605be7566fb47fd95827..1f0e959d086065fe9c126dd1d42a015f2c47395a 100644 (file)
@@ -8,6 +8,7 @@ setup(name            = 'xen',
       author_email    = 'mike.wray@hp.com',
       packages        = ['xen',
                          'xen.ext',
+                         'xen.util',
                          'xen.xend',
                          'xen.xend.server',
                          'xen.xm',
diff --git a/tools/xenctl/Makefile b/tools/xenctl/Makefile
deleted file mode 100644 (file)
index 7dc74a1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-all:
-       python setup.py build
-
-install: all
-       if [ "$(prefix)" = "" ]; then                   \
-           python setup.py install;                    \
-       elif [ "$(dist)" = "yes" ]; then                \
-           python setup.py install --home="$(prefix)"; \
-       else                                            \
-           python setup.py install --root="$(prefix)"; \
-       fi
-
-clean:
-       rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/xenctl/lib/__init__.py b/tools/xenctl/lib/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tools/xenctl/lib/console_client.py b/tools/xenctl/lib/console_client.py
deleted file mode 100644 (file)
index 7ac63ae..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-
-##############################################
-# Console client for Xen guest OSes
-# Copyright (c) 2004, K A Fraser
-##############################################
-
-import errno, os, signal, socket, struct, sys
-
-from termios import *
-# Indexes into termios.tcgetattr() list.
-IFLAG  = 0
-OFLAG  = 1
-CFLAG  = 2
-LFLAG  = 3
-ISPEED = 4
-OSPEED = 5
-CC     = 6
-
-def __child_death(signum, frame):
-    global stop
-    stop = True
-
-def __recv_from_sock(sock):
-    global stop
-    stop = False
-    while not stop:
-        try:
-            data = sock.recv(1024)
-            os.write(1, data)
-        except socket.error, error:
-            if error[0] != errno.EINTR:
-                raise
-    os.wait()
-
-def __send_to_sock(sock):
-    while 1:
-        data = os.read(0,1024)
-        if ord(data[0]) == ord(']')-64:
-            break
-        try:
-            sock.send(data)
-        except socket.error, error:
-            if error[0] == errno.EPIPE:
-                sys.exit(0)
-            if error[0] != errno.EINTR:
-                raise
-    sys.exit(0)
-
-def connect(host,port):
-    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
-    sock.connect((host,port))
-
-    oattrs = tcgetattr(0)
-    nattrs = tcgetattr(0)
-    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
-    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
-    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
-    nattrs[CFLAG] = nattrs[CFLAG] | CS8
-    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
-    nattrs[CC][VMIN] = 1
-    nattrs[CC][VTIME] = 0
-
-    if os.fork():
-        signal.signal(signal.SIGCHLD, __child_death)
-        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
-        tcsetattr(0, TCSAFLUSH, nattrs)
-        try:
-            __recv_from_sock(sock)
-        finally:
-            tcsetattr(0, TCSAFLUSH, oattrs)
-            print
-            print "************ REMOTE CONSOLE EXITED *****************"
-    else:
-        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
-        __send_to_sock(sock)
-
-if __name__ == '__main__':
-    if len(sys.argv) != 3:
-        print sys.argv[0] + " <host> <port>"
-        sys.exit(1)
-    connect(str(sys.argv[1]),int(sys.argv[2]))
diff --git a/tools/xenctl/lib/ip.py b/tools/xenctl/lib/ip.py
deleted file mode 100644 (file)
index 8396e0d..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-import os
-import re
-import socket
-import struct
-
-def readlines(fd):
-    """Version of readlines safe against EINTR.
-    """
-    import errno
-    
-    lines = []
-    while 1:
-        try:
-            line = fd.readline()
-        except IOError, ex:
-            if ex.errno == errno.EINTR:
-                continue
-            else:
-                raise
-        if line == '': break
-        lines.append(line)
-    return lines
-
-def readline(fd):
-    """Version of readline safe against EINTR.
-    """
-    while 1:
-        try:
-            return fd.readline()
-        except IOError, ex:
-            if ex.errno == errno.EINTR:
-                continue
-            else:
-                raise
-
-##### Networking-related functions
-
-"""Bridge for network backend.
-When bridging is used, eth0 may not have an IP address,
-as it may have been moved onto the bridge.
-"""
-NBE_BRIDGE = 'nbe-br'
-
-def get_current_ipaddr(dev='eth0'):
-    """Return a string containing the primary IP address for the given
-    network interface (default 'eth0').
-    """
-    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
-                       line )
-        if m:
-            return m.group(1)
-    if dev == 'eth0':
-        return get_current_ipaddr(NBE_BRIDGE)
-    return None
-
-def get_current_ipmask(dev='eth0'):
-    """Return a string containing the primary IP netmask for the given
-    network interface (default 'eth0').
-    """
-    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
-                       line )
-        if m:
-            return m.group(1)
-    if dev == 'eth0':
-        return get_current_ipmask(NBE_BRIDGE)
-    return None
-
-def get_current_ipgw(dev='eth0'):
-    """Return a string containing the IP gateway for the given
-    network interface (default 'eth0').
-    """
-    fd = os.popen( '/sbin/route -n' )
-    lines = readlines(fd)
-    for line in lines:
-        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
-                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
-        if m:
-            return m.group(1)
-    if dev == 'eth0':
-        return get_current_ipgw(NBE_BRIDGE)
-    return None
-
-def inet_aton(addr):
-    """Convert an IP addr in IPv4 dot notation into an int.
-    """
-    b = socket.inet_aton(addr)
-    return struct.unpack('!I', b)[0]
-
-def inet_ntoa(n):
-    """Convert an int into an IP addr in IPv4 dot notation.
-    """
-    b = struct.pack('!I', n)
-    return socket.inet_ntoa(b)
-
-def add_offset_to_ip(addr, offset):
-    """Add a numerical offset to an IP addr in IPv4 dot notation.
-    """
-    n = inet_aton(addr)
-    n += offset
-    return inet_ntoa(n)
-
-def check_subnet( ip, network, netmask ):
-    n_ip = inet_aton(ip)
-    n_net = inet_aton(network)
-    n_mask = inet_aton(netmask)
-    return (n_ip & n_mask) == (n_net & n_mask)
-
diff --git a/tools/xenctl/lib/tempfile.py b/tools/xenctl/lib/tempfile.py
deleted file mode 100644 (file)
index 756d8c8..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-"""Temporary files.
-
-This module provides generic, low- and high-level interfaces for
-creating temporary files and directories.  The interfaces listed
-as "safe" just below can be used without fear of race conditions.
-Those listed as "unsafe" cannot, and are provided for backward
-compatibility only.
-
-This module also provides some data items to the user:
-
-  TMP_MAX  - maximum number of names that will be tried before
-             giving up.
-  template - the default prefix for all temporary names.
-             You may change this to control the default prefix.
-  tempdir  - If this is set to a string before the first use of
-             any routine from this module, it will be considered as
-             another candidate location to store temporary files.
-"""
-
-__all__ = [
-    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
-    "mkstemp", "mkdtemp",                  # low level safe interfaces
-    "mktemp",                              # deprecated unsafe interface
-    "TMP_MAX", "gettempprefix",            # constants
-    "tempdir", "gettempdir"
-   ]
-
-
-# Imports.
-
-import os as _os
-import errno as _errno
-from random import Random as _Random
-
-if _os.name == 'mac':
-    import Carbon.Folder as _Folder
-    import Carbon.Folders as _Folders
-
-try:
-    import fcntl as _fcntl
-    # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
-    # imported, and we don't get an ImportError then.  Provoke
-    # an AttributeError instead in that case.
-    _fcntl.fcntl
-except (ImportError, AttributeError):
-    def _set_cloexec(fd):
-        pass
-else:
-    def _set_cloexec(fd):
-        flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
-        if flags >= 0:
-            # flags read successfully, modify
-            flags |= _fcntl.FD_CLOEXEC
-            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
-
-
-try:
-    import thread as _thread
-except ImportError:
-    import dummy_thread as _thread
-_allocate_lock = _thread.allocate_lock
-
-_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
-if hasattr(_os, 'O_NOINHERIT'):
-    _text_openflags |= _os.O_NOINHERIT
-if hasattr(_os, 'O_NOFOLLOW'):
-    _text_openflags |= _os.O_NOFOLLOW
-
-_bin_openflags = _text_openflags
-if hasattr(_os, 'O_BINARY'):
-    _bin_openflags |= _os.O_BINARY
-
-if hasattr(_os, 'TMP_MAX'):
-    TMP_MAX = _os.TMP_MAX
-else:
-    TMP_MAX = 10000
-
-template = "tmp"
-
-tempdir = None
-
-# Internal routines.
-
-_once_lock = _allocate_lock()
-
-class _RandomNameSequence:
-    """An instance of _RandomNameSequence generates an endless
-    sequence of unpredictable strings which can safely be incorporated
-    into file names.  Each string is six characters long.  Multiple
-    threads can safely use the same instance at the same time.
-
-    _RandomNameSequence is an iterator."""
-
-    characters = ("abcdefghijklmnopqrstuvwxyz" +
-                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
-                  "0123456789-_")
-
-    def __init__(self):
-        self.mutex = _allocate_lock()
-        self.rng = _Random()
-        self.normcase = _os.path.normcase
-
-    def __iter__(self):
-        return self
-
-    def next(self):
-        m = self.mutex
-        c = self.characters
-        choose = self.rng.choice
-
-        m.acquire()
-        try:
-            letters = [choose(c) for dummy in "123456"]
-        finally:
-            m.release()
-
-        return self.normcase(''.join(letters))
-
-def _candidate_tempdir_list():
-    """Generate a list of candidate temporary directories which
-    _get_default_tempdir will try."""
-
-    dirlist = []
-
-    # First, try the environment.
-    for envname in 'TMPDIR', 'TEMP', 'TMP':
-        dirname = _os.getenv(envname)
-        if dirname: dirlist.append(dirname)
-
-    # Failing that, try OS-specific locations.
-    if _os.name == 'mac':
-        try:
-            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
-                                              _Folders.kTemporaryFolderType, 1)
-            dirname = fsr.as_pathname()
-            dirlist.append(dirname)
-        except _Folder.error:
-            pass
-    elif _os.name == 'riscos':
-        dirname = _os.getenv('Wimp$ScrapDir')
-        if dirname: dirlist.append(dirname)
-    elif _os.name == 'nt':
-        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
-    else:
-        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
-
-    # As a last resort, the current directory.
-    try:
-        dirlist.append(_os.getcwd())
-    except (AttributeError, _os.error):
-        dirlist.append(_os.curdir)
-
-    return dirlist
-
-def _get_default_tempdir():
-    """Calculate the default directory to use for temporary files.
-    This routine should be called exactly once.
-
-    We determine whether or not a candidate temp dir is usable by
-    trying to create and write to a file in that directory.  If this
-    is successful, the test file is deleted.  To prevent denial of
-    service, the name of the test file must be randomized."""
-
-    namer = _RandomNameSequence()
-    dirlist = _candidate_tempdir_list()
-    flags = _text_openflags
-
-    for dir in dirlist:
-        if dir != _os.curdir:
-            dir = _os.path.normcase(_os.path.abspath(dir))
-        # Try only a few names per directory.
-        for seq in xrange(100):
-            name = namer.next()
-            filename = _os.path.join(dir, name)
-            try:
-                fd = _os.open(filename, flags, 0600)
-                fp = _os.fdopen(fd, 'w')
-                fp.write('blat')
-                fp.close()
-                _os.unlink(filename)
-                del fp, fd
-                return dir
-            except (OSError, IOError), e:
-                if e[0] != _errno.EEXIST:
-                    break # no point trying more names in this directory
-                pass
-    raise IOError, (_errno.ENOENT,
-                    ("No usable temporary directory found in %s" % dirlist))
-
-_name_sequence = None
-
-def _get_candidate_names():
-    """Common setup sequence for all user-callable interfaces."""
-
-    global _name_sequence
-    if _name_sequence is None:
-        _once_lock.acquire()
-        try:
-            if _name_sequence is None:
-                _name_sequence = _RandomNameSequence()
-        finally:
-            _once_lock.release()
-    return _name_sequence
-
-
-def _mkstemp_inner(dir, pre, suf, flags):
-    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
-
-    names = _get_candidate_names()
-
-    for seq in xrange(TMP_MAX):
-        name = names.next()
-        file = _os.path.join(dir, pre + name + suf)
-        try:
-            fd = _os.open(file, flags, 0600)
-            _set_cloexec(fd)
-            return (fd, file)
-        except OSError, e:
-            if e.errno == _errno.EEXIST:
-                continue # try again
-            raise
-
-    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
-
-
-# User visible interfaces.
-
-def gettempprefix():
-    """Accessor for tempdir.template."""
-    return template
-
-tempdir = None
-
-def gettempdir():
-    """Accessor for tempdir.tempdir."""
-    global tempdir
-    if tempdir is None:
-        _once_lock.acquire()
-        try:
-            if tempdir is None:
-                tempdir = _get_default_tempdir()
-        finally:
-            _once_lock.release()
-    return tempdir
-
-def mkstemp(suffix="", prefix=template, dir=None, text=False):
-    """mkstemp([suffix, [prefix, [dir, [text]]]])
-    User-callable function to create and return a unique temporary
-    file.  The return value is a pair (fd, name) where fd is the
-    file descriptor returned by os.open, and name is the filename.
-
-    If 'suffix' is specified, the file name will end with that suffix,
-    otherwise there will be no suffix.
-
-    If 'prefix' is specified, the file name will begin with that prefix,
-    otherwise a default prefix is used.
-
-    If 'dir' is specified, the file will be created in that directory,
-    otherwise a default directory is used.
-
-    If 'text' is specified and true, the file is opened in text
-    mode.  Else (the default) the file is opened in binary mode.  On
-    some operating systems, this makes no difference.
-
-    The file is readable and writable only by the creating user ID.
-    If the operating system uses permission bits to indicate whether a
-    file is executable, the file is executable by no one. The file
-    descriptor is not inherited by children of this process.
-
-    Caller is responsible for deleting the file when done with it.
-    """
-
-    if dir is None:
-        dir = gettempdir()
-
-    if text:
-        flags = _text_openflags
-    else:
-        flags = _bin_openflags
-
-    return _mkstemp_inner(dir, prefix, suffix, flags)
-
-
-def mkdtemp(suffix="", prefix=template, dir=None):
-    """mkdtemp([suffix, [prefix, [dir]]])
-    User-callable function to create and return a unique temporary
-    directory.  The return value is the pathname of the directory.
-
-    Arguments are as for mkstemp, except that the 'text' argument is
-    not accepted.
-
-    The directory is readable, writable, and searchable only by the
-    creating user.
-
-    Caller is responsible for deleting the directory when done with it.
-    """
-
-    if dir is None:
-        dir = gettempdir()
-
-    names = _get_candidate_names()
-
-    for seq in xrange(TMP_MAX):
-        name = names.next()
-        file = _os.path.join(dir, prefix + name + suffix)
-        try:
-            _os.mkdir(file, 0700)
-            return file
-        except OSError, e:
-            if e.errno == _errno.EEXIST:
-                continue # try again
-            raise
-
-    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
-
-def mktemp(suffix="", prefix=template, dir=None):
-    """mktemp([suffix, [prefix, [dir]]])
-    User-callable function to return a unique temporary file name.  The
-    file is not created.
-
-    Arguments are as for mkstemp, except that the 'text' argument is
-    not accepted.
-
-    This function is unsafe and should not be used.  The file name
-    refers to a file that did not exist at some point, but by the time
-    you get around to creating it, someone else may have beaten you to
-    the punch.
-    """
-
-##    from warnings import warn as _warn
-##    _warn("mktemp is a potential security risk to your program",
-##          RuntimeWarning, stacklevel=2)
-
-    if dir is None:
-        dir = gettempdir()
-
-    names = _get_candidate_names()
-    for seq in xrange(TMP_MAX):
-        name = names.next()
-        file = _os.path.join(dir, prefix + name + suffix)
-        if not _os.path.exists(file):
-            return file
-
-    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
-
-class _TemporaryFileWrapper:
-    """Temporary file wrapper
-
-    This class provides a wrapper around files opened for
-    temporary use.  In particular, it seeks to automatically
-    remove the file when it is no longer needed.
-    """
-
-    def __init__(self, file, name):
-        self.file = file
-        self.name = name
-        self.close_called = False
-
-    def __getattr__(self, name):
-        file = self.__dict__['file']
-        a = getattr(file, name)
-        if type(a) != type(0):
-            setattr(self, name, a)
-        return a
-
-    # NT provides delete-on-close as a primitive, so we don't need
-    # the wrapper to do anything special.  We still use it so that
-    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
-    if _os.name != 'nt':
-
-        # Cache the unlinker so we don't get spurious errors at
-        # shutdown when the module-level "os" is None'd out.  Note
-        # that this must be referenced as self.unlink, because the
-        # name TemporaryFileWrapper may also get None'd out before
-        # __del__ is called.
-        unlink = _os.unlink
-
-        def close(self):
-            if not self.close_called:
-                self.close_called = True
-                self.file.close()
-                self.unlink(self.name)
-
-        def __del__(self):
-            self.close()
-
-def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
-                       prefix=template, dir=None):
-    """Create and return a temporary file.
-    Arguments:
-    'prefix', 'suffix', 'dir' -- as for mkstemp.
-    'mode' -- the mode argument to os.fdopen (default "w+b").
-    'bufsize' -- the buffer size argument to os.fdopen (default -1).
-    The file is created as mkstemp() would do it.
-
-    Returns a file object; the name of the file is accessible as
-    file.name.  The file will be automatically deleted when it is
-    closed.
-    """
-
-    if dir is None:
-        dir = gettempdir()
-
-    if 'b' in mode:
-        flags = _bin_openflags
-    else:
-        flags = _text_openflags
-
-    # Setting O_TEMPORARY in the flags causes the OS to delete
-    # the file when it is closed.  This is only supported by Windows.
-    if _os.name == 'nt':
-        flags |= _os.O_TEMPORARY
-
-    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
-    file = _os.fdopen(fd, mode, bufsize)
-    return _TemporaryFileWrapper(file, name)
-
-if _os.name != 'posix' or _os.sys.platform == 'cygwin':
-    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
-    # while it is open.
-    TemporaryFile = NamedTemporaryFile
-
-else:
-    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
-                      prefix=template, dir=None):
-        """Create and return a temporary file.
-        Arguments:
-        'prefix', 'suffix', 'directory' -- as for mkstemp.
-        'mode' -- the mode argument to os.fdopen (default "w+b").
-        'bufsize' -- the buffer size argument to os.fdopen (default -1).
-        The file is created as mkstemp() would do it.
-
-        Returns a file object.  The file has no name, and will cease to
-        exist when it is closed.
-        """
-
-        if dir is None:
-            dir = gettempdir()
-
-        if 'b' in mode:
-            flags = _bin_openflags
-        else:
-            flags = _text_openflags
-
-        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
-        try:
-            _os.unlink(name)
-            return _os.fdopen(fd, mode, bufsize)
-        except:
-            _os.close(fd)
-            raise
diff --git a/tools/xenctl/lib/utils.py b/tools/xenctl/lib/utils.py
deleted file mode 100644 (file)
index 69bf779..0000000
+++ /dev/null
@@ -1,944 +0,0 @@
-import os, re, socket, string, sys, tempfile, xenctl.ip
-
-##### Module variables
-
-"""Location of the Virtual Disk management database.
-   defaults to /var/db/xen_vdisks.sqlite
-"""
-VD_DB_FILE = "/var/db/xen_vdisks.sqlite"
-
-"""VBD expertise level - determines the strictness of the sanity checking.
-  This mode determines the level of complaints when disk sharing occurs
-  through the current VBD mappings.
-   0 - only allow shared mappings if both domains have r/o access (always OK)
-   1 - also allow sharing with one dom r/w and the other r/o
-   2 - allow sharing with both doms r/w
-"""
-VBD_EXPERT_MODE = 0
-
-##### Module initialisation
-
-try:
-    # try to import sqlite (not everyone will have it installed)
-    import sqlite
-except ImportError:
-    # on failure, just catch the error, don't do anything
-    pass
-
-
-##### Networking-related functions
-
-def get_current_ipaddr(dev='eth0'):
-    return xenctl.ip.get_current_ipaddr(dev)
-def get_current_ipmask(dev='eth0'):
-    return xenctl.ip.get_current_ipmask(dev)
-def get_current_ipgw(dev='eth0'):
-    return xenctl.ip.get_current_ipgw(dev)
-def setup_vfr_rules_for_vif(dom,vif,addr):
-    return xenctl.ip.setup_vfr_rules_for_vif(dom,vif,addr)
-def inet_aton(addr):
-    return xenctl.ip.inet_aton(addr)
-def inet_ntoa(n):
-    return xenctl.ip.inet_ntoa(n)
-def add_offset_to_ip(addr, offset):
-    return xenctl.ip.add_offset_to_ip(addr, offset)
-def check_subnet( ip, network, netmask ):
-    return xenctl.ip.check_subnet( ip, network, netmask )
-
-##### VBD-related Functions
-
-def blkdev_name_to_number(name):
-    """Take the given textual block-device name (e.g., '/dev/sda1',
-    'hda') and return the device number used by the OS. """
-
-    if not re.match( '/dev/', name ):
-        name = '/dev/' + name
-        
-    return os.stat(name).st_rdev
-
-# lookup_blkdev_partn_info( '/dev/sda3' )
-def lookup_raw_partn(partition):
-    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
-    and return a dictionary { device, start_sector,
-    nr_sectors, type }
-        device:       Device number of the given partition
-        start_sector: Index of first sector of the partition
-        nr_sectors:   Number of sectors comprising this partition
-        type:         'Disk' or identifying name for partition type
-    """
-
-    if not re.match( '/dev/', partition ):
-        partition = '/dev/' + partition
-
-    drive = re.split( '[0-9]', partition )[0]
-
-    if drive == partition:
-        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
-        line = fd.readline()
-        if line:
-            return [ { 'device' : blkdev_name_to_number(drive),
-                       'start_sector' : long(0),
-                       'nr_sectors' : long(line) * 2,
-                       'type' : 'Disk' } ]
-        return None
-
-    # determine position on disk
-    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
-
-    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
-    lines = fd.readlines()
-    for line in lines:
-        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
-                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
-        if m:
-            return [ { 'device' : blkdev_name_to_number(drive),
-                       'start_sector' : long(m.group(1)),
-                       'nr_sectors' : long(m.group(2)),
-                       'type' : m.group(3) } ]
-    
-    return None
-
-def lookup_disk_uname( uname ):
-    """Lookup a list of segments for either a physical or a virtual device.
-    uname [string]:  name of the device in the format \'vd:id\' for a virtual
-                     disk, or \'phy:dev\' for a physical device
-    returns [list of dicts]: list of extents that make up the named device
-    """
-    ( type, d_name ) = string.split( uname, ':' )
-
-    if type == "phy":
-        segments = lookup_raw_partn( d_name )
-    elif type == "vd":
-       segments = vd_lookup( d_name )
-
-    return segments
-
-
-##### Management of the Xen control daemon
-##### (c) Keir Fraser, University of Cambridge
-
-def xend_control_message( message ):
-    """Takes a textual control message and sends it to the 'xend' Xen
-    control daemon. Returns a dictionary containing the daemon's multi-part
-    response."""
-    tmpdir = tempfile.mkdtemp()
-    try:
-        ctl = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
-        ctl.bind(tmpdir+'/sock')
-        ctl.sendto(message, '/var/run/xend/management_sock')
-        data, addr = ctl.recvfrom(2048)
-        ctl.close()
-    finally:
-        if os.path.exists(tmpdir+'/sock'):
-            os.unlink(tmpdir+'/sock')
-        if os.path.exists(tmpdir):
-            os.rmdir(tmpdir)    
-    return eval(data)
-
-
-##### VD Management-related functions
-
-##### By Mark Williamson, <mark.a.williamson@intel.com>
-##### (C) Intel Research Cambridge
-
-# TODO:
-#
-# Plenty of room for enhancement to this functionality (contributions
-# welcome - and then you get to have your name in the source ;-)...
-#
-# vd_unformat() : want facilities to unallocate virtual disk
-# partitions, possibly migrating virtual disks of them, with checks to see if
-# it's safe and options to force it anyway
-#
-# vd_create() : should have an optional argument specifying a physical
-# disk preference - useful to allocate for guest doms to do RAID
-#
-# vd_undelete() : add ability to "best effort" undelete as much of a
-# vdisk as is left in the case that some of it has already been
-# reallocated.  Some people might still be able to recover some of
-# their data this way, even if some of the disk has disappeared.
-#
-# It'd be nice if we could wipe virtual disks for security purposes -
-# should be easy to do this using dev if=/dev/{zero,random} on each
-# extent in turn.  There could be another optional flag to vd_create
-# in order to allow this.
-#
-# Error codes could be more expressive - i.e. actually tell why the
-# error occurred rather than "it broke".  Currently the code avoids
-# using exceptions to make control scripting simpler and more
-# accessible to beginners - therefore probably should just use more
-# return codes.
-#
-# Enhancements / additions to the example scripts are also welcome:
-# some people will interact with this code mostly through those
-# scripts.
-#
-# More documentation of how this stuff should be used is always nice -
-# if you have a novel configuration that you feel isn't discussed
-# enough in the HOWTO (which is currently a work in progress), feel
-# free to contribute a walkthrough, or something more substantial.
-#
-
-
-def __vd_no_database():
-    """Called when no database found - exits with an error
-    """
-    print >> sys.stderr, "ERROR: Could not locate the database file at " + VD_DB_FILE
-    sys.exit(1)
-
-
-def vd_format(partition, extent_size_mb):
-    """Format a partition or drive for use a virtual disk storage.
-    partition [string]: device file representing the partition
-    extent_size_mb [string]: extent size in megabytes to use on this disk
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        vd_init_db(VD_DB_FILE)
-    
-    if not re.match( '/dev/', partition ):
-        partition = '/dev/' + partition
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("select * from vdisk_part where partition = \'"
-               + partition + "\'")
-    row = cu.fetchone()
-
-    extent_size = extent_size_mb * 2048 # convert megabytes to sectors
-    
-    if not row:
-        part_info = lookup_raw_partn(partition)[0]
-        
-        cu.execute("INSERT INTO vdisk_part(partition, part_id, extent_size) " +
-                   "VALUES ( \'" + partition + "\', "
-                   + str(blkdev_name_to_number(partition))
-                   + ", " + str(extent_size) + ")")
-
-
-        cu.execute("SELECT max(vdisk_extent_no) FROM vdisk_extents "
-                   + "WHERE vdisk_id = 0")
-        
-        max_id, = cu.fetchone()
-
-        if max_id != None:
-            new_id = max_id + 1
-        else:
-            new_id = 0
-
-        num_extents = part_info['nr_sectors'] / extent_size
-
-        for i in range(num_extents):
-            sql ="""INSERT INTO vdisk_extents(vdisk_extent_no, vdisk_id,
-                                              part_id, part_extent_no)
-                    VALUES ("""+ str(new_id + i) + ", 0, "\
-                               + str(blkdev_name_to_number(partition))\
-                               + ", " + str(num_extents - (i + 1)) + ")"
-            cu.execute(sql)
-
-    cx.commit()
-    cx.close()
-    return 0
-
-
-def vd_create(size_mb, expiry):
-    """Create a new virtual disk.
-    size_mb [int]: size in megabytes for the new virtual disk
-    expiry [int]: expiry time in seconds from now
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    size = size_mb * 2048
-
-    cu.execute("SELECT max(vdisk_id) FROM vdisks")
-    max_id, = cu.fetchone()
-    new_id = int(max_id) + 1
-
-    # fetch a list of extents from the expired disks, along with information
-    # about their size
-    cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
-                         vdisk_extents.part_id, extent_size
-                  FROM vdisks NATURAL JOIN vdisk_extents
-                                                  NATURAL JOIN vdisk_part
-                  WHERE expires AND expiry_time <= datetime('now')
-                  ORDER BY expiry_time ASC, vdisk_extent_no DESC
-               """)  # aims to reuse the last extents
-                     # from the longest-expired disks first
-
-    allocated = 0
-
-    if expiry:
-        expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
-        expires = 1
-    else:
-        expiry_ts = "NULL"
-        expires = 0
-
-    # we'll use this to build the SQL statement we want
-    building_sql = "INSERT INTO vdisks(vdisk_id, size, expires, expiry_time)" \
-                   +" VALUES ("+str(new_id)+", "+str(size)+ ", "              \
-                   + str(expires) + ", " + expiry_ts + "); "
-
-    counter = 0
-
-    while allocated < size:
-        row = cu.fetchone()
-        if not row:
-            print "ran out of space, having allocated %d meg of %d" % (allocated, size)
-            cx.close()
-            return -1
-        
-
-        (vdisk_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
-        allocated += extent_size
-        building_sql += "UPDATE vdisk_extents SET vdisk_id = " + str(new_id) \
-                        + ", " + "vdisk_extent_no = " + str(counter)         \
-                        + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
-                        + " AND vdisk_id = " + str(vdisk_id) + "; "
-
-        counter += 1
-        
-
-    # this will execute the SQL query we build to store details of the new
-    # virtual disk and allocate space to it print building_sql
-    cu.execute(building_sql)
-    
-    cx.commit()
-    cx.close()
-    return str(new_id)
-
-
-def vd_lookup(id):
-    """Lookup a Virtual Disk by ID.
-    id [string]: a virtual disk identifier
-    Returns [list of dicts]: a list of extents as dicts, containing fields:
-                             device : Linux device number of host disk
-                             start_sector : within the device
-                             nr_sectors : size of this extent
-                             type : set to \'VD Extent\'
-                             
-                             part_device : Linux device no of host partition
-                             part_start_sector : within the partition
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("-- types int")
-    cu.execute("""SELECT COUNT(*)
-                  FROM vdisks
-                  WHERE (expiry_time > datetime('now') OR NOT expires)
-                              AND vdisk_id = """ + id)
-    count, = cu.fetchone()
-
-    if not count:
-        cx.close()
-        return None
-
-    cu.execute("SELECT size from vdisks WHERE vdisk_id = " + id)
-    real_size, = cu.fetchone()
-  
-    # This query tells PySQLite how to convert the data returned from the
-    # following query - the use of the multiplication confuses it otherwise ;-)
-    # This row is significant to PySQLite but is syntactically an SQL comment.
-
-    cu.execute("-- types str, int, int, int")
-
-    # This SQL statement is designed so that when the results are fetched they
-    # will be in the right format to return immediately.
-    cu.execute("""SELECT partition, vdisk_part.part_id,
-                         round(part_extent_no * extent_size) as start,
-                         extent_size
-                         
-                  FROM vdisks NATURAL JOIN vdisk_extents
-                                             NATURAL JOIN vdisk_part
-                                                
-                  WHERE vdisk_extents.vdisk_id = """ + id
-               + " ORDER BY vdisk_extents.vdisk_extent_no ASC"
-               )
-
-    extent_tuples = cu.fetchall()
-
-    # use this function to map the results from the database into a dict
-    # list of extents, for consistency with the rest of the code
-    def transform ((partition, part_device, part_offset, nr_sectors)):
-        return {
-                 # the disk device this extent is on - for passing to Xen
-                 'device' : lookup_raw_partn(partition)[0]['device'],
-                 # the offset of this extent within the disk - for passing to Xen
-                 'start_sector' : long(part_offset + lookup_raw_partn(partition)[0]['start_sector']),
-                 # extent size, in sectors
-                 'nr_sectors' : nr_sectors,
-                 # partition device this extent is on (useful to know for xenctl.utils fns)
-                 'part_device' : part_device,
-                 # start sector within this partition (useful to know for xenctl.utils fns)
-                 'part_start_sector' : part_offset,
-                 # type of this extent - handy to know
-                 'type' : 'VD Extent' }
-
-    cx.commit()
-    cx.close()
-
-    extent_dicts = map(transform, extent_tuples)
-
-    # calculate the over-allocation in sectors (happens because
-    # we allocate whole extents)
-    allocated_size = 0
-    for i in extent_dicts:
-        allocated_size += i['nr_sectors']
-
-    over_allocation = allocated_size - real_size
-
-    # trim down the last extent's length so the resulting VBD will be the
-    # size requested, rather than being rounded up to the nearest extent
-    extent_dicts[len(extent_dicts) - 1]['nr_sectors'] -= over_allocation
-
-    return extent_dicts
-
-
-def vd_enlarge(vdisk_id, extra_size_mb):
-    """Create a new virtual disk.
-    vdisk_id [string]   :    ID of the virtual disk to enlarge
-    extra_size_mb  [int]:    size in megabytes to increase the allocation by
-    returns  [int]      :    0 on success, otherwise non-zero
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    extra_size = extra_size_mb * 2048
-
-    cu.execute("-- types int")
-    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id
-               + " AND (expiry_time > datetime('now') OR NOT expires)")
-    count, = cu.fetchone()
-
-    if not count: # no such vdisk
-        cx.close()
-        return -1
-
-    cu.execute("-- types int")
-    cu.execute("""SELECT SUM(extent_size)
-                  FROM vdisks NATURAL JOIN vdisk_extents
-                                         NATURAL JOIN vdisk_part
-                  WHERE vdisks.vdisk_id = """ + vdisk_id)
-
-    real_size, = cu.fetchone() # get the true allocated size
-
-    cu.execute("-- types int")
-    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
-
-    old_size, = cu.fetchone()
-
-
-    cu.execute("--- types int")
-    cu.execute("""SELECT MAX(vdisk_extent_no)
-                  FROM vdisk_extents
-                  WHERE vdisk_id = """ + vdisk_id)
-
-    counter = cu.fetchone()[0] + 1 # this stores the extent numbers
-
-
-    # because of the extent-based allocation, the VD may already have more
-    # allocated space than they asked for.  Find out how much we really
-    # need to add.
-    add_size = extra_size + old_size - real_size
-
-    # fetch a list of extents from the expired disks, along with information
-    # about their size
-    cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
-                         vdisk_extents.part_id, extent_size
-                  FROM vdisks NATURAL JOIN vdisk_extents
-                                                  NATURAL JOIN vdisk_part
-                  WHERE expires AND expiry_time <= datetime('now')
-                  ORDER BY expiry_time ASC, vdisk_extent_no DESC
-               """)  # aims to reuse the last extents
-                     # from the longest-expired disks first
-
-    allocated = 0
-
-    building_sql = "UPDATE vdisks SET size = " + str(old_size + extra_size)\
-                   + " WHERE vdisk_id = " + vdisk_id + "; "
-
-    while allocated < add_size:
-        row = cu.fetchone()
-        if not row:
-            cx.close()
-            return -1
-
-        (dead_vd_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
-        allocated += extent_size
-        building_sql += "UPDATE vdisk_extents SET vdisk_id = " + vdisk_id    \
-                        + ", " + "vdisk_extent_no = " + str(counter)         \
-                        + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
-                        + " AND vdisk_id = " + str(dead_vd_id) + "; "
-
-        counter += 1
-        
-
-    # this will execute the SQL query we build to store details of the new
-    # virtual disk and allocate space to it print building_sql
-    cu.execute(building_sql)
-    
-    cx.commit()
-    cx.close()
-    return 0
-
-
-def vd_undelete(vdisk_id, expiry_time):
-    """Create a new virtual disk.
-    vdisk_id      [int]: size in megabytes for the new virtual disk
-    expiry_time   [int]: expiry time, in seconds from now
-    returns       [int]: zero on success, non-zero on failure
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-
-    if vdisk_id == '0': #  undeleting vdisk 0 isn't sane!
-        return -1
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("-- types int")
-    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id)
-    count, = cu.fetchone()
-
-    if not count:
-        cx.close()
-        return -1
-
-    cu.execute("-- types int")
-    cu.execute("""SELECT SUM(extent_size)
-                  FROM vdisks NATURAL JOIN vdisk_extents
-                                         NATURAL JOIN vdisk_part
-                  WHERE vdisks.vdisk_id = """ + vdisk_id)
-
-    real_size, = cu.fetchone() # get the true allocated size
-
-
-    cu.execute("-- types int")
-    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
-
-    old_size, = cu.fetchone()
-
-    if real_size < old_size:
-        cx.close()
-        return -1
-
-    if expiry_time == 0:
-        expires = '0'
-    else:
-        expires = '1'
-
-    # this will execute the SQL query we build to store details of the new
-    # virtual disk and allocate space to it print building_sql
-    cu.execute("UPDATE vdisks SET expiry_time = datetime('now','"
-               + str(expiry_time) + " seconds'), expires = " + expires
-               + " WHERE vdisk_id = " + vdisk_id)
-    
-    cx.commit()
-    cx.close()
-    return 0
-
-
-
-
-def vd_list():
-    """Lists all the virtual disks registered in the system.
-    returns [list of dicts]
-    """
-    
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("""SELECT vdisk_id, size, expires, expiry_time
-                  FROM vdisks
-                  WHERE (NOT expires) OR expiry_time > datetime('now')
-               """)
-
-    ret = cu.fetchall()
-
-    cx.close()
-
-    def makedicts((vdisk_id, size, expires, expiry_time)):
-        return { 'vdisk_id' : str(vdisk_id), 'size': size,
-                 'expires' : expires, 'expiry_time' : expiry_time }
-
-    return map(makedicts, ret)
-
-
-def vd_refresh(id, expiry):
-    """Change the expiry time of a virtual disk.
-    id [string]  : a virtual disk identifier
-    expiry [int] : expiry time in seconds from now (0 = never expire)
-    returns [int]: zero on success, non-zero on failure
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-    
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("-- types int")
-    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
-               + " AND (expiry_time > datetime('now') OR NOT expires)")
-    count, = cu.fetchone()
-
-    if not count:
-        cx.close()
-        return -1
-
-    if expiry:
-        expires = 1
-        expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
-    else:
-        expires = 0
-        expiry_ts = "NULL"
-
-    cu.execute("UPDATE vdisks SET expires = " + str(expires)
-               + ", expiry_time = " + expiry_ts
-               + " WHERE (expiry_time > datetime('now') OR NOT expires)"
-               + " AND vdisk_id = " + id)
-
-    cx.commit()
-    cx.close()
-    
-    return 0
-
-
-def vd_delete(id):
-    """Deletes a Virtual Disk, making its extents available for future VDs.
-       id [string]   : identifier for the virtual disk to delete
-       returns [int] : 0 on success, -1 on failure (VD not found
-                       or already deleted)
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-    
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("-- types int")
-    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
-               + " AND (expiry_time > datetime('now') OR NOT expires)")
-    count, = cu.fetchone()
-
-    if not count:
-        cx.close()
-        return -1
-
-    cu.execute("UPDATE vdisks SET expires = 1, expiry_time = datetime('now')"
-               + " WHERE vdisk_id = " + id)
-
-    cx.commit()
-    cx.close()
-    
-    return 0
-
-
-def vd_freespace():
-    """Returns the amount of free space available for new virtual disks, in MB
-    returns [int] : free space for VDs in MB
-    """
-
-    if not os.path.isfile(VD_DB_FILE):
-        __vd_no_database()
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("-- types int")
-
-    cu.execute("""SELECT SUM(extent_size)
-                  FROM vdisks NATURAL JOIN vdisk_extents
-                                           NATURAL JOIN vdisk_part
-                  WHERE expiry_time <= datetime('now') AND expires""")
-
-    sum, = cu.fetchone()
-
-    cx.close()
-
-    return sum / 2048
-
-
-def vd_init_db(path):
-    """Initialise the VD SQLite database
-    path [string]: path to the SQLite database file
-    """
-
-    cx = sqlite.connect(path)
-    cu = cx.cursor()
-
-    cu.execute(
-        """CREATE TABLE vdisk_extents
-                           ( vdisk_extent_no INT,
-                             vdisk_id INT,
-                             part_id INT,
-                             part_extent_no INT )
-        """)
-
-    cu.execute(
-        """CREATE TABLE vdisk_part
-                           ( part_id INT,
-                             partition VARCHAR,
-                             extent_size INT )
-        """)
-
-    cu.execute(
-        """CREATE TABLE vdisks
-                           ( vdisk_id INT,
-                             size INT,
-                             expires BOOLEAN,
-                             expiry_time TIMESTAMP )
-        """)
-
-
-    cu.execute(
-        """INSERT INTO vdisks ( vdisk_id, size, expires, expiry_time )
-                       VALUES ( 0,        0,    1,       datetime('now') )
-        """)
-
-    cx.commit()
-    cx.close()
-
-    VD_DB_FILE = path
-
-
-
-def vd_cp_to_file(vdisk_id,filename):
-    """Writes the contents of a specified vdisk out into a disk file, leaving
-    the original copy in the virtual disk pool."""
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    extents = vd_lookup(vdisk_id)
-
-    if not extents:
-        return -1
-    
-    file_idx = 0 # index into source file, in sectors
-
-    for i in extents:
-        cu.execute("""SELECT partition, extent_size FROM vdisk_part
-                      WHERE part_id =  """ + str(i['part_device']))
-
-        (partition, extent_size) = cu.fetchone()
-
-        os.system("dd bs=1b if=" + partition + " of=" + filename
-                  + " skip=" + str(i['part_start_sector'])
-                  + " seek=" + str(file_idx)
-                  + " count=" + str(i['nr_sectors'])
-                  + " > /dev/null")
-
-        file_idx += i['nr_sectors']
-
-    cx.close()
-
-    return 0 # should return -1 if something breaks
-    
-
-def vd_mv_to_file(vdisk_id,filename):
-    """Writes a vdisk out into a disk file and frees the space originally
-    taken within the virtual disk pool.
-    vdisk_id [string]: ID of the vdisk to write out
-    filename [string]: file to write vdisk contents out to
-    returns [int]: zero on success, nonzero on failure
-    """
-
-    if vd_cp_to_file(vdisk_id,filename):
-        return -1
-
-    if vd_delete(vdisk_id):
-        return -1
-
-    return 0
-
-
-def vd_read_from_file(filename,expiry):
-    """Reads the contents of a file directly into a vdisk, which is
-    automatically allocated to fit.
-    filename [string]: file to read disk contents from
-    returns [string] : vdisk ID for the destination vdisk
-    """
-
-    size_bytes = os.stat(filename).st_size
-
-    (size_mb,leftover) =  divmod(size_bytes,1048580) # size in megabytes
-    if leftover > 0: size_mb += 1 # round up if not an exact number of MB
-
-    vdisk_id = vd_create(size_mb, expiry)
-
-    if vdisk_id < 0:
-        return -1
-
-    cx = sqlite.connect(VD_DB_FILE)
-    cu = cx.cursor()
-
-    cu.execute("""SELECT partition, extent_size, part_extent_no
-                  FROM vdisk_part NATURAL JOIN vdisk_extents
-                  WHERE vdisk_id =  """ + vdisk_id + """
-                  ORDER BY vdisk_extent_no ASC""")
-
-    extents = cu.fetchall()
-
-    size_sectors = size_mb * 2048 # for feeding to dd
-
-    file_idx = 0 # index into source file, in sectors
-
-    def write_extent_to_vd((partition, extent_size, part_extent_no),
-                           file_idx, filename):
-        """Write an extent out to disk and update file_idx"""
-
-        os.system("dd bs=512 if=" + filename + " of=" + partition
-                  + " skip=" + str(file_idx)
-                  + " seek=" + str(part_extent_no * extent_size)
-                  + " count=" + str(min(extent_size, size_sectors - file_idx))
-                  + " > /dev/null")
-
-        return extent_size
-
-    for i in extents:
-        file_idx += write_extent_to_vd(i, file_idx, filename)
-
-    cx.close()
-
-    return vdisk_id
-    
-
-
-
-def vd_extents_validate(new_extents,new_writeable):
-    """Validate the extents against the existing extents.
-    Complains if the list supplied clashes against the extents that
-    are already in use in the system.
-    new_extents [list of dicts]: list of new extents, as dicts
-    new_writeable [int]: 1 if they are to be writeable, 0 otherwise
-    returns [int]: either the expertise level of the mapping if it doesn't
-                   exceed VBD_EXPERT_MODE or -1 if it does (error)
-    """
-
-    import Xc # this is only needed in this function
-
-    xc = Xc.new()
-
-    ##### Probe for explicitly created virtual disks and build a list
-    ##### of extents for comparison with the ones that are being added
-
-    probe = xc.vbd_probe()
-
-    old_extents = [] # this will hold a list of all existing extents and
-                     # their writeable status, as a list of (device,
-                     # start, size, writeable?) tuples
-
-    for vbd in probe:
-        this_vbd_extents = xc.vbd_getextents(vbd['dom'],vbd['vbd'])
-        for vbd_ext in this_vbd_extents:
-            vbd_ext['writeable'] = vbd['writeable']
-            old_extents.append(vbd_ext)
-            
-    ##### Now scan /proc/mounts for compile a list of extents corresponding to
-    ##### any devices mounted in DOM0.  This list is added on to old_extents
-
-    regexp = re.compile("/dev/(\S*) \S* \S* (..).*")
-    fd = open('/proc/mounts', "r")
-
-    while True:
-        line = fd.readline()
-        if not line: # if we've run out of lines then stop reading
-            break
-        
-        m = regexp.match(line)
-
-        # if the regexp didn't match then it's probably a line we don't
-        # care about - skip to next line
-        if not m:
-            continue
-
-        # lookup the device
-        ext_list = lookup_raw_partn(m.group(1))
-
-        # if lookup failed, skip to next mounted device
-        if not ext_list:
-            continue
-
-        # set a writeable flag as appropriate
-        for ext in ext_list:
-            ext['writeable'] = m.group(2) == 'rw'
-
-        # now we've got here, the contents of ext_list are in a
-        # suitable format to be added onto the old_extents list, ready
-        # for checking against the new extents
-
-        old_extents.extend(ext_list)
-
-    fd.close() # close /proc/mounts
-
-    ##### By this point, old_extents contains a list of extents, in
-    ##### dictionary format corresponding to every extent of physical
-    ##### disk that's either part of an explicitly created VBD, or is
-    ##### mounted under DOM0.  We now check these extents against the
-    ##### proposed additions in new_extents, to see if a conflict will
-    ##### happen if they are added with write status new_writeable
-
-    level = 0 # this'll accumulate the max warning level
-
-    # Search for clashes between the new extents and the old ones
-    # Takes time O(len(new_extents) * len(old_extents))
-    for new_ext in new_extents:
-        for old_ext in old_extents:
-            if(new_ext['device'] == old_ext['device']):
-
-                new_ext_start = new_ext['start_sector']
-                new_ext_end = new_ext_start + new_ext['nr_sectors'] - 1
-                
-                old_ext_start = old_ext['start_sector']
-                old_ext_end = old_ext_start + old_ext['nr_sectors'] - 1
-                
-                if((old_ext_start <= new_ext_start <= old_ext_end) or
-                   (old_ext_start <= new_ext_end <= old_ext_end)):
-                    if (not old_ext['writeable']) and new_writeable:
-                        level = max(1,level)
-                    elif old_ext['writeable'] and (not new_writeable):
-                        level = max(1,level)
-                    elif old_ext['writeable'] and new_writeable:
-                        level = max(2,level)
-
-
-    ##### level now holds the warning level incurred by the current
-    ##### VBD setup and we complain appropriately to the user
-
-
-    if level == 1:
-        print >> sys.stderr, """Warning: one or more hard disk extents
-         writeable by one domain are also readable by another."""
-    elif level == 2:
-        print >> sys.stderr, """Warning: one or more hard disk extents are
-         writeable by two or more domains simultaneously."""
-
-    if level > VBD_EXPERT_MODE:
-        print >> sys.stderr, """ERROR: This kind of disk sharing is not allowed
-        at the current safety level (%d).""" % VBD_EXPERT_MODE
-        level = -1
-
-    return level
-
diff --git a/tools/xenctl/setup.py b/tools/xenctl/setup.py
deleted file mode 100644 (file)
index 03f3f1e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-from distutils.core import setup, Extension
-import sys
-
-modules = [ 'xenctl.console_client', 'xenctl.utils', 'xenctl.ip' ]
-
-# We need the 'tempfile' module from Python 2.3. We install this ourselves
-# if the installed Python is older than 2.3.
-major = sys.version_info[0]
-minor = sys.version_info[1]
-if major == 2 and minor < 3:
-    modules.append('xenctl.tempfile')
-
-setup(name = 'xenctl',
-      version = '1.0',
-      py_modules = modules,
-      package_dir = { 'xenctl' : 'lib' },
-      )
-
diff --git a/tools/xu/Makefile b/tools/xu/Makefile
new file mode 100644 (file)
index 0000000..6b31fd1
--- /dev/null
@@ -0,0 +1,15 @@
+
+all:
+       python setup.py build
+
+install: all
+       if [ "$(prefix)" = "" ]; then                   \
+           python setup.py install;                    \
+       elif [ "$(dist)" = "yes" ]; then                \
+           python setup.py install --home="$(prefix)"; \
+       else                                            \
+           python setup.py install --root="$(prefix)"; \
+       fi
+
+clean:
+       rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm